/**
 * Matrix.as
 * Copyright 2014 Qunhe Tech, all rights reserved.
 * Qunhe PROPRIETARY/CONFIDENTIAL, any form of usage is subject to approval.
 */
package org.bridge.flash.hi2048.model.core
{
    import org.bridge.flash.hi2048.model.constants.OperationType;

    /**
     * two-dimensional matrix holds the game numbers
     * @author zhangshuai
     */
    public class Matrix
    {
        public static const DIM:int = 4;
        private var mNumArray:Array = new Array;

        public function Matrix()
        {
            for (var i:int = 0; i < DIM; i++)
            {
                var array:Array = [{n: 0}, {n: 0}, {n: 0}, {n: 0}];
                mNumArray.push(array);
            }
        }

        public function operate(operationType:int):int
        {
            var spareNum:int = 0;
            for (var i:int = 0; i < DIM; i++)
            {
                var row:Array = fetchRow(operationType, i);
                var temp:int = 0;
                var k:int = 0;
                for (var j:int = 0; j < DIM; j++)
                {
                    if (row[j].n == 0)
                    {
                        continue;
                    }
                    if (temp == row[j].n)
                    {
                        row[k++].n = temp * 2;
                    }
                    else
                    {
                        if (temp != 0)
                        {
                            row[k++].n = temp;
                        }
                        temp = row[j].n;
                    }
                }

                for (; k < DIM; k++)
                {
                    spareNum += 1;
                    row[k].n = 0;
                }
            }
            return spareNum;
        }

        public function randomOne():void
        {
            var spareArray:Array = new Array;
            for (var i:int = 0; i < DIM; i++)
            {
                var row:Array = mNumArray[i] as Array;
                for (var j:int = 0; j < DIM; j++)
                {
                    if (row[j].n == 0)
                    {
                        spareArray.push(row[j]);
                    }
                }
            }

            var index:int = Math.round(Math.random() * (spareArray.length - 1));
            var value:int = Math.random() < 0.5 ? 2 : 4;
            spareArray[index].n = value;
        }

        private function fetchRow(operationType:int, index:int):Array
        {
            switch (operationType)
            {
                case OperationType.LEFT:
                {
                    return mNumArray[index];
                }
                case OperationType.RIGHT:
                {
                    return (mNumArray[index] as Array).reverse();
                }
                case OperationType.UP:
                {
                    var row:Array = new Array;
                    for (var i:int = 0; i++; i < 0)
                    {
                        row.push(mNumArray[i][index]);
                    }
                }
                case OperationType.DOWN:
                {
                    return row.reverse();
                }
                case OperationType.UP:
                {
                    return row;
                }
            }
            return null;
        }

        public function fetchOne(i:int, j:int):Object
        {
            return mNumArray[i][j];
        }
    }
}
